#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <tuple>
#include <vector>
#include <queue>
#include <atomic>

class ThreadPool
{
public:
    ThreadPool(std::size_t poolSize=std::thread::hardware_concurrency())
    {
        for(int i=0;i<poolSize;i++)
        {
            _works.emplace_back([this](){
                while(true)
                {
                    std::function<void()>task;
                    {
                        std::unique_lock<std::mutex>lock(_mutex);
                        _con.wait(lock,[this](){
                            return _stop||!_tasks.empty();
                        });
                        if (_stop && _tasks.empty()) {
                            return;
                        }
                        task=std::move(_tasks.front());
                        _tasks.pop();
                    }
                    try {
                        task(); // 执行任务
                    } catch (...) {
                        // 记录异常或忽略，但保持线程存活
                    }
                }
            });
        }
    }
    void Close()
    {
        {
            std::unique_lock<std::mutex>lock(_mutex);
            _stop=true;
        }
        
        _con.notify_all();
    }
    ~ThreadPool()
    {
        Close();
        for(int i=0;i<_works.size();i++)
        {
            if(_works[i].joinable())
            {
                _works[i].join();
            }
        }
    }
    template<typename F,typename ...Args>
    void Enqueue(F&&f,Args&&...args)
    {
        std::unique_lock<std::mutex>lock(_mutex);
        if (_stop) {
            throw std::runtime_error("ThreadPool is closed");
        }
        _tasks.emplace([f=std::forward<F>(f),args=std::make_tuple(std::forward<Args>(args)...)](){
            std::apply(f,args);
        });
        _con.notify_one();
    }
private:
    std::queue<std::function<void()>>_tasks;
    std::vector<std::thread>_works;
    std::mutex _mutex;
    std::condition_variable _con;
    std::atomic<bool> _stop;
};